package field

import (
	"errors"
	"math"
	"sync"

	"gitee.com/yanwc/net/utils"
)

type (
	SerialNumber    uint16  // 消息头序列号
	SerialNumberRaw [2]byte // 消息头序列号
)

func (sn SerialNumber) Raw() (out SerialNumberRaw) {
	copy(out[:], utils.NumberToBytesWithBigEndian(sn))
	return
}

func (snr SerialNumberRaw) Type() SerialNumber {
	return utils.BytesToNumber[SerialNumber](snr[:])
}

func (sn SerialNumberRaw) Slice() []byte {
	return sn[:]
}

var ErrNotEnoughSerialNumber = errors.New("序号不足")

type serialNumberFactory struct {
	mutex sync.Mutex
	Data  map[SerialNumber]bool
}

// 获取可用序列号
func (sn *serialNumberFactory) Take() (SerialNumber, error) {
	sn.mutex.Lock()
	defer sn.mutex.Unlock()
	for i := SerialNumber(0); i < math.MaxUint16; i++ {
		if _, ok := sn.Data[i]; ok {
			continue
		}

		sn.Data[i] = true
		return i, nil
	}

	return 0, ErrNotEnoughSerialNumber
}

// 释放序列号
func (sn *serialNumberFactory) Release(v SerialNumber) {
	sn.mutex.Lock()
	defer sn.mutex.Unlock()
	delete(sn.Data, v)
}

// 是否包含序列号
func (sn *serialNumberFactory) Contain(v SerialNumber) bool {
	_, ok := sn.Data[v]
	return ok
}

// 序列号生成工厂
func NewSerialNumberFactory() *serialNumberFactory {
	return &serialNumberFactory{
		Data: make(map[SerialNumber]bool, 10),
	}
}
